package com.ht.demo.service.aspect;

import com.alibaba.fastjson.JSON;
import com.ht.demo.common.appexception.ResultData;
import com.ht.demo.common.constans.SystemConstant;
import com.ht.demo.common.pojo.bo.monitor.SysLoggerBO;
import com.ht.demo.common.pojo.bo.system.SysUserBO;
import com.ht.demo.common.util.JsonUtil;
import com.ht.demo.service.annotation.LoggerInfo;
import com.ht.demo.service.manager.async.AsyncManager;
import com.ht.demo.service.manager.async.factory.*;
import com.ht.demo.service.system.UserTokenManager;
import com.ht.demo.service.util.ServletUtils;
import com.ht.demo.service.util.ip.IpUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.NamedThreadLocal;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Map;

/**
 * @Author hdengxian
 * @Date 2023/5/30 14:14
 */
@Aspect
@Component
public class LoggerInfoAspect {
    /** 计算操作消耗时间 */
    private static final ThreadLocal<Long> TIME_LOCAL = new NamedThreadLocal("Cost Time");

    /**
     * 请求处理前执行
     * @param joinPoint
     * @param loggerInfo
     */
    @Before(value = "@annotation(loggerInfo)")
    public void doBefore(JoinPoint joinPoint, LoggerInfo loggerInfo) {
        TIME_LOCAL.set(System.currentTimeMillis());
    }

    /**
     * 处理完请求后执行
     * @param joinPoint
     * @param loggerInfo
     * @param json
     */
    @AfterReturning(pointcut = "@annotation(loggerInfo)", returning = "json")
    public void doAfter(JoinPoint joinPoint, LoggerInfo loggerInfo, ResultData json) {
        handleLogInfo(joinPoint, loggerInfo, json);
    }

    /**
     * 处理日志
     *
     * @param joinPoint
     * @param loggerInfo
     * @param json
     */
    protected void handleLogInfo(final JoinPoint joinPoint, LoggerInfo loggerInfo, ResultData json) {
        SysLoggerBO loggerBO = new SysLoggerBO();
        loggerBO.setTitle(loggerInfo.title());
        loggerBO.setOperateType(loggerInfo.operateType().getCode());
        String ip = IpUtils.getIpAddr();
        // 设置方法名称
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        //请求方式
        HttpServletRequest request = ServletUtils.getRequest();
        String type = request.getMethod();
        loggerBO.setOperUrl(request.getRequestURL().toString());
        SysUserBO loginUser = UserTokenManager.getInstance().getLoginUser();
        if (loginUser != null) {
            loggerBO.setOperName(loginUser.getUserName());
        }

        loggerBO.setOperIp(ip);
        loggerBO.setClazzName(className);
        loggerBO.setMethod(methodName);
        loggerBO.setRequestType(type);

        if (json.getCode().intValue() == 20000) {
            String requestValue = getRequestValue(joinPoint);
            if (requestValue.length() > 2000) {
                loggerBO.setOperParam(requestValue.substring(0, 2000));
            } else {
                loggerBO.setOperParam(requestValue);
            }
            String resJson = JsonUtil.toJson(json);
            if (resJson.length() > 2000) {
                loggerBO.setJsonResult(resJson.substring(0, 2000));
            } else {
                loggerBO.setJsonResult(resJson);
            }
            loggerBO.setStatus(SystemConstant.STR_0);
        } else {
            loggerBO.setErrorMsg(json.getMessage());
            loggerBO.setStatus(SystemConstant.STR_1);
        }

        loggerBO.setOperTime(new Date());
        loggerBO.setCostTime(System.currentTimeMillis() - TIME_LOCAL.get());

        AsyncManager.getInstance().execute(AsyncFactory.recordOperate(loggerBO));

    }

    /**
     * 获取请求参数
     * @param joinPoint
     * @return
     */
    private String getRequestValue(JoinPoint joinPoint) {
        Map<?, ?> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
        String method = ServletUtils.getRequest().getMethod();

        if ((paramsMap == null || paramsMap.isEmpty()) && (HttpMethod.PUT.name().equals(method) || HttpMethod.POST.name().equals(method))) {
            String params = argsArrayToString(joinPoint.getArgs());
            return params;
        } else {
            String jsonParam = JSON.toJSONString(paramsMap);
            String params = "";
            if (jsonParam.length() > 2000) {
                params = jsonParam.substring(0, 2000);
                return params;
            }
            return jsonParam;
        }
    }

    /**
     * 拼接请求参数
     * @param args
     * @return
     */
    private String argsArrayToString(Object[] args) {
        if (args == null || args.length <= 0) {
            return "";
        }
        StringBuffer buffer = new StringBuffer();
        for (Object o : args) {
            if (o != null) {
                String jsonObj = JSON.toJSONString((o));
                buffer.append(jsonObj);
            }
        }
        return buffer.toString();
    }


}
